package com.inspectortime.webapp;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindException;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;

import com.inspectortime.domain.Inspection;
import com.inspectortime.domain.type.LockboxType;
import com.inspectortime.domain.type.PresentAtInspectionType;
import com.inspectortime.domain.type.State;
import com.inspectortime.repository.Factory;
import com.inspectortime.repository.Repository;
import com.inspectortime.util.SpringValidatorUtils;
import com.inspectortime.webapp.util.CustomStateEditor;
import com.inspectortime.webapp.util.FlexibleNumberPropertyEditor;
import com.inspectortime.webapp.util.HttpSessionUtils;

public class InspectionReserveTimeController extends SimpleFormController {

	private static Log log = LogFactory.getLog(InspectionReserveTimeController.class);

	private Factory factory;
	private Repository repository;

	public InspectionReserveTimeController() {
		super();
		
	}
	
	protected Map referenceData(HttpServletRequest request) throws Exception {
		Map<String, Object> data = new HashMap<String, Object>();		
		data.put("lockboxTypes", LockboxType.values());
		data.put("presentAtInspectionOptions", PresentAtInspectionType.values());
		data.put("allStates", State.values());
		return data;
	}
	
	protected Object formBackingObject(HttpServletRequest request) throws Exception {
		
		InspectionCriteria inspectionCriteria = new InspectionCriteria();
		
		// the user may be entering this page by clicking a link in an email
		// if so, load inspection from passed in id and add it to session
		String emailedInspectionId = request.getParameter("id");
		if (StringUtils.hasText(emailedInspectionId)) {
			Inspection inspection = repository
					.loadInspection(emailedInspectionId);
			inspectionCriteria.setInspection(inspection);
			HttpSessionUtils.storeWizardInspection(request, inspection.getId());
		} else {
			inspectionCriteria.setInspection(HttpSessionUtils.retrieveWizardInspection(request, repository));	
		}
		
		//prepare empty data objects for the upcoming page
		if (inspectionCriteria.getInspection().getSecondHomeBuyer() == null) {
			// Note this is being set on the criteria only (so that we don't persist an empty one)
			inspectionCriteria.setSecondHomeBuyer(factory.createHomeBuyer());
		} else {
			inspectionCriteria.setSecondHomeBuyer(inspectionCriteria.getInspection().getSecondHomeBuyer());
		}
		
		return inspectionCriteria;
	}


	protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command,
			BindException errors) throws Exception {

		InspectionCriteria inspectionCriteria = (InspectionCriteria) command;
		Inspection inspection = inspectionCriteria.getInspection();
		
		//the validator will ensure that all fields are properly filled out for the second home buyer, if any of them are. 
		//so, if first name is filled out, assume user the rest of the second buyer info is valid
		if (StringUtils.hasText(inspectionCriteria.getSecondHomeBuyer().getName().getFirst())) {
			inspection.setSecondHomeBuyer(inspectionCriteria.getSecondHomeBuyer());
		} else {
			inspection.setSecondHomeBuyer(null);
		}

		// if this is an incomplete schedule, let's generate a unique code
		// for future reference...
		// TODO: Not in use right now, but consider re-introducing later to prevent e-mail reminder link reuse
		if (!StringUtils.hasText(inspection.getInspectionCode())) {
			inspection.generateInspectionCode();
		}

		// Handle inspection command object
		inspection.save();

		//set inspectionId in session
		HttpSessionUtils.storeWizardInspection(request, inspection.getId());
		
		return new ModelAndView(this.getSuccessView());
		
	}

	
	/**
	 * Override empty parent method to log validation errors for debugging purposes only. Can be
	 * removed.
	 */
	protected void onBindAndValidate(HttpServletRequest request, Object command, BindException errors) throws Exception {
		// For debugging only: Log all validation errors
		SpringValidatorUtils.logValidationErrors(log, errors);
	}

	protected void initBinder(HttpServletRequest request,
			ServletRequestDataBinder binder) throws Exception {
		// Feb 4, 2008 8:00:00 AM
		DateFormat df = new SimpleDateFormat("MMM dd, yyyy hh:mm:ss a");
		df.setLenient(true);
		CustomDateEditor editor = new CustomDateEditor(df, false);
		binder.registerCustomEditor(Date.class, editor);
		binder.registerCustomEditor(State.class, new CustomStateEditor());
		
		binder.registerCustomEditor(Integer.class, "inspection.property.constructionYear",
				new FlexibleNumberPropertyEditor("0000", Integer.class));

	}
	
	public void setFactory(Factory factory) {
		this.factory = factory;
	}

	public void setRepository(Repository repository) {
		this.repository = repository;
	}

	
}
